package com.mindbox.mudx

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.res.Configuration
import android.os.Bundle
import android.os.Handler
import android.os.SystemClock
import android.util.Log
import android.view.KeyCharacterMap
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.SurfaceHolder
import android.view.SurfaceView
import android.view.inputmethod.CompletionInfo
import android.view.inputmethod.CorrectionInfo
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.ExtractedText
import android.view.inputmethod.ExtractedTextRequest
import android.view.inputmethod.InputConnection
import android.view.inputmethod.InputContentInfo
import android.view.inputmethod.InputMethodManager

class MainView(context: Context) : SurfaceView(context), SurfaceHolder.Callback2 {
    init {
        holder.addCallback(this)
        isFocusableInTouchMode = true
    }

    private var xloop: XLoopHolder = XLoopHolder("main")

    fun onCreate(savedInstanceState: Bundle?) {
        xloop.onCreate(context,savedInstanceState)
    }

    fun onDestroy() {
        xloop.onDestroy()
    }

    fun onStart() {
        xloop.onStart()
    }

    fun onStop() {
        xloop.onStop()
    }

    fun onResume() {
        xloop.onResume()
    }

    fun onPause() {
        xloop.onPause()
    }

    override fun surfaceCreated(holder: SurfaceHolder) {
        xloop.surfaceCreated(holder)
    }

    override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
        xloop.surfaceChanged(holder, format, width, height)
    }

    override fun surfaceDestroyed(holder: SurfaceHolder) {
        xloop.surfaceDestroyed(holder)
    }

    override fun surfaceRedrawNeeded(holder: SurfaceHolder) {
        xloop.surfaceRedrawNeeded(holder)
    }

    override fun onConfigurationChanged(newConfig: Configuration) {
        xloop.onConfigurationChanged(newConfig)
    }

    private fun onKeyNative(event: KeyEvent): Boolean {
        return xloop.onKey(event)
    }

    private fun onTouchNative(event: MotionEvent): Boolean {
        return xloop.onTouch(event)
    }

    private fun onCommitEnd(data: String) {
        xloop.onCommitEnd(data)
    }

    private fun onCommitBack() {
        xloop.onCommitBack()
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent?): Boolean {
        Log.i("MainView", event.toString())
        if (event != null) {
            val x = event.x
            val y = event.y
            when (event.action) {
                MotionEvent.ACTION_DOWN -> {
                    val mImm: InputMethodManager = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
                    if (x < 500 && y < 500) {
                        Log.i("MainView", "version3")
                        this.requestFocus()
                        mImm.showSoftInput(this, 0)
                    } else {
                        mImm.hideSoftInputFromWindow(this.windowToken, 0)
                        this.clearFocus()
                    }
                }
            }
            if (this.onTouchNative(event)) {
                return true
            }
        }
        return super.onTouchEvent(event)
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        Log.i("MainView", event.toString())
        if (event != null) {
            if (this.onKeyNative(event)) {
                return true
            }
        }
        return super.onKeyDown(keyCode, event)
    }

    override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
        Log.i("MainView", event.toString())
        if (event != null) {
            if (this.onKeyNative(event)) {
                return true
            }
        }
        return super.onKeyUp(keyCode, event)
    }

    override fun onCreateInputConnection(outAttrs: EditorInfo?): InputConnection {
        return InputConn(this)
    }

    class InputConn(view: MainView) : InputConnection {
        // 键盘隐藏时放弃Focus
        private val mView = view
        override fun getTextBeforeCursor(n: Int, flags: Int): CharSequence? {
            Log.i("InputConn", "getTextBeforeCursor $n $flags")
            return null
        }

        override fun getTextAfterCursor(n: Int, flags: Int): CharSequence? {
            Log.i("InputConn", "getTextAfterCursor $n $flags")
            return null
        }

        override fun getSelectedText(flags: Int): CharSequence? {
            Log.i("InputConn", "getSelectedText $flags")
            return null
        }

        override fun getCursorCapsMode(reqModes: Int): Int {
            Log.i("InputConn", "getCursorCapsMode $reqModes")
            return 0
        }

        override fun getExtractedText(request: ExtractedTextRequest?, flags: Int): ExtractedText? {
            Log.i("InputConn", "getExtractedText $request $flags")
            return null
        }

        override fun deleteSurroundingText(beforeLength: Int, afterLength: Int): Boolean {
            Log.i("InputConn", "deleteSurroundingText $beforeLength $afterLength")
            val eventTime = SystemClock.uptimeMillis()
            sendKeyEvent(
                KeyEvent(
                    eventTime,
                    eventTime,
                    KeyEvent.ACTION_DOWN,
                    KeyEvent.KEYCODE_DEL,
                    0,
                    0,
                    KeyCharacterMap.VIRTUAL_KEYBOARD,
                    0,
                    KeyEvent.FLAG_SOFT_KEYBOARD or KeyEvent.FLAG_KEEP_TOUCH_MODE or KeyEvent.FLAG_EDITOR_ACTION
                )
            )
            sendKeyEvent(
                KeyEvent(
                    eventTime,
                    eventTime,
                    KeyEvent.ACTION_UP,
                    KeyEvent.KEYCODE_DEL,
                    0,
                    0,
                    KeyCharacterMap.VIRTUAL_KEYBOARD,
                    0,
                    (KeyEvent.FLAG_SOFT_KEYBOARD or KeyEvent.FLAG_KEEP_TOUCH_MODE or KeyEvent.FLAG_EDITOR_ACTION)
                )
            )
            return false
        }

        override fun deleteSurroundingTextInCodePoints(beforeLength: Int, afterLength: Int): Boolean {
            Log.i("InputConn", "deleteSurroundingTextInCodePoints $beforeLength $afterLength")
            return false
        }

        override fun setComposingText(text: CharSequence?, newCursorPosition: Int): Boolean {
            Log.i("InputConn", "setComposingText $text $newCursorPosition")
            return false
        }

        override fun setComposingRegion(start: Int, end: Int): Boolean {
            Log.i("InputConn", "setComposingRegion $start $end")
            return false
        }

        override fun finishComposingText(): Boolean {
            Log.i("InputConn", "finishComposingText")
            return false
        }

        override fun commitText(text: CharSequence?, newCursorPosition: Int): Boolean {
            Log.i("InputConn", "commitText $text $newCursorPosition")
            if (text != null) {
                mView.onCommitEnd(text.toString())
            }
            return false
        }

        override fun commitCompletion(text: CompletionInfo?): Boolean {
            Log.i("InputConn", "commitCompletion $text")
            return false
        }

        override fun commitCorrection(correctionInfo: CorrectionInfo?): Boolean {
            Log.i("InputConn", "commitCorrection $correctionInfo")
            return false
        }

        override fun setSelection(start: Int, end: Int): Boolean {
            Log.i("InputConn", "setSelection $start $end")
            return false
        }

        override fun performEditorAction(editorAction: Int): Boolean {
            Log.i("InputConn", "performEditorAction $editorAction")
            val eventTime = SystemClock.uptimeMillis()
            when (editorAction) {
                0 -> {
                    sendKeyEvent(
                        KeyEvent(
                            eventTime,
                            eventTime,
                            KeyEvent.ACTION_DOWN,
                            KeyEvent.KEYCODE_ENTER,
                            0,
                            0,
                            KeyCharacterMap.VIRTUAL_KEYBOARD,
                            0,
                            KeyEvent.FLAG_SOFT_KEYBOARD or KeyEvent.FLAG_KEEP_TOUCH_MODE or KeyEvent.FLAG_EDITOR_ACTION
                        )
                    )
                    sendKeyEvent(
                        KeyEvent(
                            eventTime,
                            eventTime,
                            KeyEvent.ACTION_UP,
                            KeyEvent.KEYCODE_ENTER,
                            0,
                            0,
                            KeyCharacterMap.VIRTUAL_KEYBOARD,
                            0,
                            (KeyEvent.FLAG_SOFT_KEYBOARD or KeyEvent.FLAG_KEEP_TOUCH_MODE or KeyEvent.FLAG_EDITOR_ACTION)
                        )
                    )
                }
            }
            return false
        }

        override fun performContextMenuAction(id: Int): Boolean {
            Log.i("InputConn", "performContextMenuAction $id")
            return false
        }

        override fun beginBatchEdit(): Boolean {
            Log.i("InputConn", "beginBatchEdit")
            return false
        }

        override fun endBatchEdit(): Boolean {
            Log.i("InputConn", "endBatchEdit")
            return false
        }

        override fun sendKeyEvent(event: KeyEvent?): Boolean {
            Log.i("InputConn", "sendKeyEvent $event")
            if (event != null) {
                when (event.keyCode) {
                    KeyEvent.KEYCODE_DEL -> {
                        if (event.action == KeyEvent.ACTION_DOWN) {
                            mView.onCommitBack()
                        }
                    }

                    KeyEvent.KEYCODE_ENTER -> {
                        if (event.action == KeyEvent.ACTION_DOWN) {
                            mView.onCommitEnd("\n")
                        }
                    }
                }
                mView.onKeyNative(event)
            }
            return false
        }

        override fun clearMetaKeyStates(states: Int): Boolean {
            Log.i("InputConn", "clearMetaKeyStates $states")
            return false
        }

        override fun reportFullscreenMode(enabled: Boolean): Boolean {
            Log.i("InputConn", "reportFullscreenMode $enabled")
            return false
        }

        override fun performPrivateCommand(action: String?, data: Bundle?): Boolean {
            Log.i("InputConn", "performPrivateCommand $action $data")
            return false
        }

        override fun requestCursorUpdates(cursorUpdateMode: Int): Boolean {
            Log.i("InputConn", "requestCursorUpdates $cursorUpdateMode")
            return false
        }

        override fun getHandler(): Handler? {
            Log.i("InputConn", "getHandler")
            return null
        }

        override fun closeConnection() {
            Log.i("InputConn", "closeConnection")
        }

        override fun commitContent(inputContentInfo: InputContentInfo, flags: Int, opts: Bundle?): Boolean {
            Log.i("InputConn", "commitContent $inputContentInfo $flags $opts")
            return false
        }
    }
}